home *** CD-ROM | disk | FTP | other *** search
- Subject: time conversion / time zone system
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 4, Issue 14
- Submitted by: talcott!seismo!elsie!ado
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # Makefile
- # settz.3
- # tzfile.5
- # tzcomp.8
- # tzfile.h
- # tzcomp.c
- # scheck.c
- # strchr.c
- # mkdir.c
- # tzdump.c
- # settz.c
- # years.sh
- # asia
- # australasia
- # europe
- # etcetera
- # northamerica
- # pacificnew
- # This archive created: Fri Mar 7 17:02:24 1986
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'README'" '(620 characters)'
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat << \SHAR_EOF > 'README'
- @(#)README 2.1
-
- Please send comments or information to seismo!elsie!ado (with, perhaps,
- carbon copes to cbosgd!mark, seismo!linus!encore!necis!geo, and
- seismo!munnari!kre, who are responsible for any good ideas that show up here).
-
- Historical local time information has been included here not because it should
- be part of the standard (or, indeed, anyone's product), but rather to:
-
- * give people an idea of the variety of local time rules that have
- existed in the past and thus an idea of the variety that may be
- expected in the future;
-
- * provide a test of the generality of the local time rule description
- system.
- SHAR_EOF
- if test 620 -ne "`wc -c < 'README'`"
- then
- echo shar: error transmitting "'README'" '(should have been 620 characters)'
- fi
- fi
- echo shar: extracting "'Makefile'" '(1713 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- # @(#)Makefile 2.1
-
- # If you want something other than Eastern United States time used on your
- # system, change the line below (after finding the zone you want in the
- # time zone files, or adding it to a time zone file).
- # Alternately, if you discover you've got the wrong time zone, you can just
- # tzcomp -l rightzone
-
- LOCALTIME= Eastern
-
- # Use an absolute path name for TZDIR unless you're just testing the software.
-
- TZDIR= /etc/tzdir
-
- # LINTFLAGS is set for 4.1bsd systems. If you're using System V, you'll want
- # to comment out the "LINTFLAGS=" line.
-
- LINTFLAGS= -phbaaxc
-
- DEBUG=
- LFLAGS=
- CFLAGS= $(DEBUG) -O -DOBJECTID -DTZDIR=\"$(TZDIR)\"
-
- TZCSRCS= tzcomp.c scheck.c strchr.c mkdir.c
- TZCOBJS= tzcomp.o scheck.o strchr.o mkdir.o
- TZDSRCS= tzdump.c settz.c
- TZDOBJS= tzdump.o settz.o
- DOCS= README Makefile settz.3 tzfile.5 tzcomp.8
- SOURCES= tzfile.h $(TZCSRCS) $(TZDSRCS) years.sh
- DATA= asia australasia europe etcetera northamerica pacificnew
- ENCHILADA= $(DOCS) $(SOURCES) $(DATA)
-
- all: REDID_BINARIES tzdump
-
- REDID_BINARIES: $(TZDIR) tzcomp $(DATA) years
- tzcomp -l $(LOCALTIME) -d $(TZDIR) $(DATA)
- cp /dev/null $@
-
- tzdump: $(TZDOBJS)
- $(CC) $(LFLAGS) $(TZDOBJS) -o $@
-
- tzcomp: $(TZCOBJS)
- $(CC) $(LFLAGS) $(TZCOBJS) -o $@
-
- $(TZDIR):
- mkdir $@
-
- years: years.sh
- rm -f $@
- cp $? $@
- chmod 555 $@
-
- BUNDLE1: $(DOCS)
- bundle $(DOCS) > BUNDLE1
-
- BUNDLE2: $(SOURCES)
- bundle $(SOURCES) > BUNDLE2
-
- BUNDLE3: $(DATA)
- bundle $(DATA) > BUNDLE3
-
- $(ENCHILADA):
- sccs get $(REL) $(REV) $@
-
- sure: $(TZCSRCS) $(TZDSRCS)
- lint $(LINTFLAGS) $(TZCSRCS)
- lint $(LINTFLAGS) $(TZDSRCS)
-
- clean:
- rm -f core *.o *.out REDID_BINARIES years tzdump tzcomp BUNDLE \#*
-
- CLEAN: clean
- sccs clean
-
- tzdump.o tzcomp.o settz.o: tzfile.h
- SHAR_EOF
- if test 1713 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 1713 characters)'
- fi
- fi
- echo shar: extracting "'settz.3'" '(1606 characters)'
- if test -f 'settz.3'
- then
- echo shar: will not over-write existing file "'settz.3'"
- else
- cat << \SHAR_EOF > 'settz.3'
- .TH SETTZ 3
- .SH NAME
- settz, newctime, newlocaltime \- convert date and time to ASCII
- .SH SYNOPSIS
- .nf
- .B settz(zonename)
- .B char *zonename;
- .PP
- .B char *newctime(clock)
- .B long *clock;
- .PP
- .B
- #include "time.h"
- .PP
- .B struct tm *newlocaltime(clock)
- .B long *clock;
- .PP
- .B char *tz_abbr;
- .SH DESCRIPTION
- .I Settz
- sets time conversion information used by
- .IR newlocaltime .
- If
- .I zonename
- begins with a slash,
- it is used as the absolute pathname of the
- .IR tzfile (5)-format
- file from which to read the time conversion information;
- if
- .I zonename
- begins with some other character,
- it is used as a pathname relative to the standard time conversion information
- directory. A call of the form
- .ti +.5i
- .B
- settz("")
- .br
- causes built-in information about GMT to be used; a call of the form
- .ti +.5i
- .B
- settz((char *) 0)
- .br
- is treated as if it were a call of the form
- .ti +.5i
- .B
- settz("localtime")
- .PP
- .I Newlocaltime
- has the same argument and return value as
- .IR localtime .
- If
- .I newlocaltime
- is called before
- .I settz
- is called,
- .I newlocaltime
- calls
- .I settz
- with the value returned by
- .B
- getenv("TZ").
- .I Newlocaltime
- sets
- tz_abbr
- to a pointer to an
- ASCII string that's the time zone abbreviation to be used with
- .IR newlocaltime 's
- return value.
- .PP
- .I Newctime
- returns
- .IR "asctime(newlocaltime(*clock))" .
- .SH DIAGNOSTICS
- .I Settz
- returns zero if all seems well; it returns negative one otherwise
- (and sets things up so that its built-in information about GMT is used).
- .SH FILES
- /etc/tzdir standard time conversion information directory
- .SH "SEE ALSO"
- ctime(3), getenv(3), tzfile(5)
- .. @(#)settz.3 2.1
- SHAR_EOF
- if test 1606 -ne "`wc -c < 'settz.3'`"
- then
- echo shar: error transmitting "'settz.3'" '(should have been 1606 characters)'
- fi
- fi
- echo shar: extracting "'tzfile.5'" '(2100 characters)'
- if test -f 'tzfile.5'
- then
- echo shar: will not over-write existing file "'tzfile.5'"
- else
- cat << \SHAR_EOF > 'tzfile.5'
- .TH TZFILE 5
- .SH NAME
- tzfile \- time zone information
- .SH SYNOPSIS
- .B
- #include "tzfile.h"
- .SH DESCRIPTION
- The time zone information files used by
- .IR settz (3)
- and
- .IR newlocaltime (3)
- begin with a
- .I tzinfo
- structure (as defined in the include file
- .B
- "tzfile.h"\c
- ):
- .sp
- .nf
- .in +.5i
- .ta .5i +\w'unsigned short 'u
- struct tzhead {
- char tzh_reserved[14];
- unsigned short tzh_timecnt;
- unsigned short tzh_typecnt;
- unsigned short tzh_charcnt;
- };
- .in -.5i
- .fi
- .PP
- The
- .B tzh_reserved
- element is currently unused.
- The
- .B tzh_timecnt
- element gives the number of "transition times" for which data is stored
- in the file;
- the
- .B tzh_typecnt
- (which must not be zero)
- element gives the number of "local time types" for which data is stored
- in the file;
- and the
- .B tzh_charcnt
- element gives the number of characters of "time zone abbreviation strings"
- stored in the file.
- .PP
- The above header is followed by
- .B tzh_timecnt
- values of type
- .BR long ,
- sorted in ascending order;
- each is used as a transition time (as returned by
- .IR time (2))
- at which the rules for computing local time change.
- Next come
- .B tzh_timecnt
- values of type
- .BR "unsigned char" ;
- each one tells which of the different types of "local time" described in the
- file is associated with the same-indexed transition time.
- These values serve as indices into an array of
- .B ttinfo
- structures that appears next in the file;
- these structures are defined as follows:
- .in +.5i
- .sp
- .nf
- .ta .5i +\w'unsigned short 'u
- struct ttinfo {
- long tt_gmtoff;
- int tt_isdst;
- unsigned int tt_abbrind;
- };
- .in -.5i
- .fi
- .sp
- In each structure,
- .B tt_gmtoff
- gives the number of seconds to be added to GMT,
- .B
- tt_isdst
- tells whether
- .B
- tm_isdst
- should be set by
- .IR newlocaltime (3),
- and
- .B tt_abbrind
- serves as an index into the array of time zone abbreviation chaaracters
- that follow the
- .B ttinfo
- structure(s) in the file.
- .PP
- .I Newlocaltime
- uses the first
- .B ttinfo
- structure in the file
- if either
- .B tzh_timecnt
- is zero or
- .IR newlocaltime 's
- argument is less than
- the first transition time recorded in the file.
- .SH SEE ALSO
- settz(3)
- .. @(#)tzfile.5 2.1
- SHAR_EOF
- if test 2100 -ne "`wc -c < 'tzfile.5'`"
- then
- echo shar: error transmitting "'tzfile.5'" '(should have been 2100 characters)'
- fi
- fi
- echo shar: extracting "'tzcomp.8'" '(5479 characters)'
- if test -f 'tzcomp.8'
- then
- echo shar: will not over-write existing file "'tzcomp.8'"
- else
- cat << \SHAR_EOF > 'tzcomp.8'
- .TH TZCOMP 8
- .SH NAME
- tzcomp \- time zone compiler
- .SH SYNOPSIS
- .B tzcomp
- [
- .B \-d
- directory ] [
- .B \-l
- localtime ] [ filename ... ]
- .SH DESCRIPTION
- .I Tzcomp
- reads text from the file(s) named on the command line
- and creates the time conversion information files specified in this input.
- If a
- .I filename
- is
- .BR ` - ',
- the standard input is read.
- .PP
- These options are available:
- .TP
- .BI "\-d " directory
- Create time conversion information files in the named directory rather than
- in the standard directory named below.
- .TP
- .BI "\-l " localtime
- Use the given time zone as local time.
- .PP
- Input lines are made up of fields.
- Fields are separated from one another by any number of white space characters.
- Leading and trailing white space on input lines is ignored.
- An unquoted sharp character (#) in the input introduces a comment which extends
- to the end of the line the sharp character appears on.
- White space characters and sharp characters may be enclosed in double quotes
- (") if they're to be used as part of a field.
- Any line which is blank (after comment stripping) is ignored.
- Non-blank lines are expected to be of one of three
- types: rule lines, zone lines, and link lines.
- .PP
- A rule line has the form
- .nf
- .B
- .ti +.5i
- .ta \w'Rule 'u +\w'MostNA 'u +\w'FROM 'u +\w'1973 'u +\w'TYPE 'u +\w'Apr 'u +\w'lastSun 'u +\w'2:00 'u +\w'SAVE 'u
- .sp
- Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
- .sp
- For example:
- .ti +.5i
- .sp
- Rule MostNA 1969 1973 - Apr lastSun 2:00 1:00 D
- .sp
- .fi
- The fields that make up a rule line are:
- .TP
- .B NAME
- Gives the (arbitrary) name of the set of rules this rule is part of.
- .TP
- .B FROM
- Gives the first year in which the rule applies.
- .TP
- .B TO
- Gives the last year in which the rule applies.
- The word
- .RB ` only '
- may be used to repeat the value of the
- .B
- FROM
- field.
- .TP
- .B TYPE
- Gives the type of year in which the year applies. If
- .B TYPE
- is
- .B
- "-"
- then the rule applies in all years between
- .B FROM
- and
- .B TO
- inclusive.
- If
- .B TYPE
- is something else, then the command
- .B
- .ti +.5i
- years from to type
- .br
- is executed with arguments
- .IR from ,
- .IR to ,
- and
- .I type
- taken from the rule line; the rule applies only in those years
- printed by the
- .I years
- command.
-
- The distributed
- .I years
- command is a shell script that handles year types
- .B uspres
- (United States presidential election years)
- and
- .B nonpres
- (all other years);
- other year types may be added by changing the script.
- .TP
- .B IN
- Names the month in which the rule takes effect. Month names may be
- abbreviated.
- .TP
- .B ON
- Gives the day on which the rule takes effect.
- Recognized forms include:
- .nf
- .in +.5i
- .sp
- .ta \w'lastSun 'u
- 5 the fifth of the month
- lastSun the last Sunday in the month
- lastMon the last Monday in the month
- Sun>=8 first Sunday on or after the eighth
- Sun<=25 last Sunday on or before the 25th
- .fi
- .in -.5i
- .sp
- Names of days of the week may be abbreviated or spelled out in full.
- Note that there must be no spaces within the
- .B ON
- field.
- .TP
- .B AT
- Gives the time of day at which the rule takes affect.
- Recognized forms include:
- .nf
- .in +.5i
- .sp
- .ta \w'1:28:13 'u
- 2 time in hours
- 2:00 time in hours and minutes
- 15:00 24-hour format time (for times after noon)
- 1:28:14 time in hours, minutes, and seconds
- .fi
- .in -.5i
- .sp
- Any of these forms may be followed by the letter 'w' if the given time is
- local "wall clock" time or 's' if the given time is local "standard" time;
- in the absence of 'w' or 's', wall clock time is assumed.
- .TP
- .B SAVE
- Gives the amount of time to be added to local standard time when the rule is in
- effect (although, of course, the 'w' and 's' suffixes are not used).
- This field has the same format as the
- .B AT
- field.
- .TP
- .B LETTER/S
- Gives the "variable part" (for example, the 'S' or 'D' in "EST" or "EDT")
- of time zone abbreviations to be used when this rule is in effect.
- If this field is
- .B
- "-",
- the variable part is null.
- .PP
- A zone line has the form
- .sp
- .nf
- .ti +.5i
- .ta \w'Zone 'u +\w'Eastern 'u +\w'GMTOFF 'u +\w'MostNA 'u
- Zone NAME GMTOFF RULES FORMAT
- .sp
- For example:
- .sp
- .ti +.5i
- Zone Eastern -5:00 MostNA E%sT
- .sp
- .fi
- The fields that make up a zone line are:
- .TP
- .B NAME
- The name of the time zone.
- This is the name used in creating the time conversion information file for the
- zone.
- .TP
- .B GMTOFF
- The amount of time to add to GMT to get standard time in this zone.
- This field has the same format as the
- .B AT
- and
- .B SAVE
- fields of rule lines;
- begin the field with a minus sign if time must be subtracted from GMT.
- .TP
- .B RULES
- The name of the rule(s) that apply in the time zone.
- If this field is
- .B
- "-"
- then standard time always applies in the time zone.
- .TP
- .B FORMAT
- The format for time zone abbreviations in this time zone.
- The pair of characters
- .B
- "%s"
- is used to show where the "variable part" of the time zone abbreviation goes.
- .PP
- A link line has the form
- .sp
- .nf
- .ti +.5i
- .ta \w'Link 'u +\w'LINK-FROM 'u
- Link LINK-FROM LINK-TO
- .sp
- For example:
- .sp
- .ti +.5i
- Link Eastern EST5EDT
- .sp
- .fi
- The
- .B LINK-FROM
- field should appear as the
- .B NAME
- field in some zone line;
- the
- .B LINK-TO
- field is used as an alternate name for that zone.
- .PP
- Lines may appear in any order in the input.
- .SH NOTE
- For areas with more than two types of local time,
- you may get to use local standard time in "AT" field of the earliest
- transition time's rule to ensure that
- the earliest transition time recorded in the compiled file is correct.
- .SH FILES
- /etc/tzdir standard directory used for created files
- .SH "SEE ALSO"
- settz(3), tzfile(5)
- .. @(#)tzcomp.8 2.1
- SHAR_EOF
- if test 5479 -ne "`wc -c < 'tzcomp.8'`"
- then
- echo shar: error transmitting "'tzcomp.8'" '(should have been 5479 characters)'
- fi
- fi
- echo shar: extracting "'tzfile.h'" '(1409 characters)'
- if test -f 'tzfile.h'
- then
- echo shar: will not over-write existing file "'tzfile.h'"
- else
- cat << \SHAR_EOF > 'tzfile.h'
- /* @(#)tzfile.h 2.1 */
-
- /*
- ** Information about time zone files.
- */
-
- #ifndef TZDIR
- #define TZDIR "/etc/tzdir" /* Time zone object file directory */
- #endif
-
- #ifndef TZDEFAULT
- #define TZDEFAULT "localtime"
- #endif
-
- struct ttinfo { /* time type information */
- long tt_gmtoff; /* GMT offset in seconds */
- int tt_isdst; /* used to set tm_isdst */
- unsigned int tt_abbrind; /* abbreviation list index */
- };
-
- /*
- ** Each file begins with. . .
- */
-
- struct tzhead {
- char tzh_reserved[14]; /* reserved for future use */
- unsigned short tzh_timecnt; /* number of transition times */
- unsigned short tzh_typecnt; /* number of local time types */
- unsigned short tzh_charcnt; /* number of abbr. chars */
- };
-
- /*
- ** . . .followed by. . .
- **
- ** tzh_timecnt (long)s transition times as returned by time(2)
- ** tzh_timecnt (unsigned char)s types of local time starting at above
- ** tzh_typecnt (struct ttinfo)s information for each time type
- ** tzh_charcnt (char)s '\0'-terminated zone abbreviaton strings
- */
-
- /*
- ** In the current implementation, "settz()" refuses to deal with files that
- ** exceed any of the limits below.
- */
-
- #ifndef TZ_MAX_TIMES
- #define TZ_MAX_TIMES 170 /* Maximum number of transition times */
- #endif
-
- #ifndef TZ_MAX_TYPES
- #define TZ_MAX_TYPES 10 /* Maximum number of local time types */
- #endif
-
- #ifndef TZ_MAX_CHARS
- #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
- #endif
- SHAR_EOF
- if test 1409 -ne "`wc -c < 'tzfile.h'`"
- then
- echo shar: error transmitting "'tzfile.h'" '(should have been 1409 characters)'
- fi
- fi
- echo shar: extracting "'tzcomp.c'" '(24558 characters)'
- if test -f 'tzcomp.c'
- then
- echo shar: will not over-write existing file "'tzcomp.c'"
- else
- cat << \SHAR_EOF > 'tzcomp.c'
- #
-
- #include "stdio.h"
-
- #ifdef OBJECTID
- static char sccsid[] = "@(#)tzcomp.c 2.1";
- #endif
-
- #include "tzfile.h"
- #include "ctype.h"
-
- #ifndef alloc_t
- #define alloc_t unsigned
- #endif
-
- #ifndef MAL
- #define MAL NULL
- #endif
-
- #ifndef BUFSIZ
- #define BUFSIZ 1024
- #endif
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
-
- #ifdef lint
- #define scheck(string, format) (format)
- #endif
- #ifndef lint
- extern char * scheck();
- #endif
-
- extern char * calloc();
- extern char * malloc();
- extern char * optarg;
- extern int optind;
- extern FILE * popen();
- extern char * realloc();
- extern char * sprintf();
- extern char * strcat();
- extern char * strchr();
- extern char * strcpy();
-
- static int errors;
- static char * filename;
- static char ** getfields();
- static int linenum;
- static char * progname;
- static long rpytime();
- static long tadd();
-
- #define SECS_PER_MIN 60L
- #define MINS_PER_HOUR 60L
- #define HOURS_PER_DAY 24L
- #define DAYS_PER_YEAR 365L /* Except in leap years */
- #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
- #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
- #define SECS_PER_YEAR (SECS_PER_DAY * DAYS_PER_YEAR)
-
- #define EPOCH_YEAR 1970
- #define EPOCH_WDAY TM_THURSDAY
-
- /*
- ** Values a la localtime(3)
- */
-
- #define TM_JANUARY 0
- #define TM_FEBRUARY 1
- #define TM_MARCH 2
- #define TM_APRIL 3
- #define TM_MAY 4
- #define TM_JUNE 5
- #define TM_JULY 6
- #define TM_AUGUST 7
- #define TM_SEPTEMBER 8
- #define TM_OCTOBER 9
- #define TM_NOVEMBER 10
- #define TM_DECEMBER 11
-
- #define TM_SUNDAY 0
- #define TM_MONDAY 1
- #define TM_TUESDAY 2
- #define TM_WEDNESDAY 3
- #define TM_THURSDAY 4
- #define TM_FRIDAY 5
- #define TM_SATURDAY 6
-
- /*
- ** Line codes.
- */
-
- #define LC_RULE 0
- #define LC_ZONE 1
- #define LC_LINK 2
-
- /*
- ** Which fields are which on a Zone line.
- */
-
- #define ZF_NAME 1
- #define ZF_GMTOFF 2
- #define ZF_RULE 3
- #define ZF_FORMAT 4
- #define ZONE_FIELDS 5
-
- /*
- ** Which files are which on a Rule line.
- */
-
- #define RF_NAME 1
- #define RF_LOYEAR 2
- #define RF_HIYEAR 3
- #define RF_COMMAND 4
- #define RF_MONTH 5
- #define RF_DAY 6
- #define RF_TOD 7
- #define RF_STDOFF 8
- #define RF_ABBRVAR 9
- #define RULE_FIELDS 10
-
- /*
- ** Which fields are which on a Link line.
- */
-
- #define LF_FROM 1
- #define LF_TO 2
- #define LINK_FIELDS 3
-
- struct rule {
- char * r_filename;
- int r_linenum;
- char * r_name;
-
- long r_loyear; /* for example, 1986 */
- long r_hiyear; /* for example, 1986 */
- char * r_yrtype;
-
- long r_month; /* 0..11 */
-
- int r_dycode; /* see below */
- long r_dayofmonth;
- long r_wday;
-
- long r_tod; /* time from midnight */
- int r_todisstd; /* above is standard time if TRUE */
- /* above is wall clock time if FALSE */
- long r_stdoff; /* offset from standard time */
- char * r_abbrvar; /* variable part of time zone abbreviation */
-
- int r_type; /* used when creating output files */
- };
-
- /*
- ** r_dycode r_dayofmonth r_wday
- */
- #define DC_DOM 0 /* 1..31 */ /* unused */
- #define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */
- #define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */
-
- static struct rule * rules;
- static int nrules; /* number of rules */
-
- struct zone {
- char * z_filename;
- int z_linenum;
-
- char * z_name;
- long z_gmtoff;
- char * z_rule;
- char * z_format;
-
- struct rule * z_rules;
- int z_nrules;
- };
-
- static struct zone * zones;
- static int nzones; /* number of zones */
-
- struct link {
- char * l_filename;
- int l_linenum;
- char * l_from;
- char * l_to;
- };
-
- static struct link * links;
- static int nlinks;
-
- struct lookup {
- char * l_word;
- long l_value;
- };
-
- static struct lookup * byword();
-
- static struct lookup line_codes[] = {
- "Rule", LC_RULE,
- "Zone", LC_ZONE,
- "Link", LC_LINK,
- NULL, 0
- };
-
- static struct lookup mon_names[] = {
- "January", TM_JANUARY,
- "February", TM_FEBRUARY,
- "March", TM_MARCH,
- "April", TM_APRIL,
- "May", TM_MAY,
- "June", TM_JUNE,
- "July", TM_JULY,
- "August", TM_AUGUST,
- "September", TM_SEPTEMBER,
- "October", TM_OCTOBER,
- "November", TM_NOVEMBER,
- "December", TM_DECEMBER,
- NULL, 0
- };
-
- static struct lookup wday_names[] = {
- "Sunday", TM_SUNDAY,
- "Monday", TM_MONDAY,
- "Tuesday", TM_TUESDAY,
- "Wednesday", TM_WEDNESDAY,
- "Thursday", TM_THURSDAY,
- "Friday", TM_FRIDAY,
- "Saturday", TM_SATURDAY,
- NULL, 0
- };
-
- static struct lookup lasts[] = {
- "last-Sunday", TM_SUNDAY,
- "last-Monday", TM_MONDAY,
- "last-Tuesday", TM_TUESDAY,
- "last-Wednesday", TM_WEDNESDAY,
- "last-Thursday", TM_THURSDAY,
- "last-Friday", TM_FRIDAY,
- "last-Saturday", TM_SATURDAY,
- NULL, 0
- };
-
- static long mon_lengths[] = { /* ". . .knuckles are 31. . ." */
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
-
- static struct tzhead h;
- static long ats[TZ_MAX_TIMES];
- static unsigned char types[TZ_MAX_TIMES];
- static struct ttinfo ttis[TZ_MAX_TYPES];
- static char chars[TZ_MAX_CHARS];
-
- /*
- ** Exits.
- */
-
- static
- tameexit()
- {
- exit(0);
- }
-
- static
- wild2exit(part1, part2)
- char * part1;
- char * part2;
- {
- register char * between;
-
- if (part1 == NULL)
- part1 = "";
- if (part2 == NULL)
- part2 = "";
- between = (*part1 == '\0' || *part2 == '\0') ? "" : " ";
- (void) fprintf(stderr, "%s: wild %s%s%s\n",
- progname, part1, between, part2);
- exit(1);
- }
-
- static
- wildexit(string)
- char * string;
- {
- wild2exit(string, (char *) NULL);
- }
-
- static
- wildrexit(string)
- char * string;
- {
- wild2exit("result from", string);
- }
-
- /*
- ** Memory allocation.
- */
-
- static char *
- emalloc(size)
- {
- register char * cp;
-
- if ((cp = malloc((alloc_t) size)) == NULL || cp == MAL)
- wildrexit("malloc");
- return cp;
- }
-
- static char *
- erealloc(ptr, size)
- char * ptr;
- {
- register char * cp;
-
- if ((cp = realloc(ptr, (alloc_t) size)) == NULL)
- wildrexit("realloc");
- return cp;
- }
-
- static char *
- eallocpy(old)
- char * old;
- {
- register char * new;
-
- if (old == NULL)
- old = "";
- new = emalloc(strlen(old) + 1);
- (void) strcpy(new, old);
- return new;
- }
-
- static
- usage()
- {
- (void) fprintf(stderr,
- "%s: usage is %s [ -l localtime ] [ -d directory ] [ filename ... ]\n",
- progname, progname);
- exit(1);
- }
-
- static char * localtime = NULL;
- static char * directory = NULL;
-
- main(argc, argv)
- int argc;
- char * argv[];
- {
- register int i;
- register int c;
-
- progname = argv[0];
- while ((c = getopt(argc, argv, "d:l:")) != EOF)
- switch (c) {
- default:
- usage();
- case 'd':
- if (directory == NULL)
- directory = optarg;
- else wildexit("multiple command line -d's");
- break;
- case 'l':
- if (localtime == NULL)
- localtime = optarg;
- else wildexit("multiple command line -l's");
- }
- if (directory == NULL)
- directory = TZDIR;
- if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
- usage(); /* usage message by request */
- zones = (struct zone *) emalloc(0);
- rules = (struct rule *) emalloc(0);
- links = (struct link *) emalloc(0);
- for (i = optind; i < argc; ++i)
- infile(argv[i]);
- if (errors)
- wildexit("input data");
- associate();
- for (i = 0; i < nzones; ++i)
- outzone(&zones[i]);
- /*
- ** We'll take the easy way out on this last part.
- */
- if (chdir(directory) != 0)
- wild2exit("result from chdir to", directory);
- for (i = 0; i < nlinks; ++i) {
- (void) unlink(links[i].l_to);
- if (link(links[i].l_from, links[i].l_to) != 0)
- wild2exit("result creating", links[i].l_to);
- }
- if (localtime != NULL) {
- (void) unlink(TZDEFAULT);
- if (link(localtime, TZDEFAULT) != 0)
- wild2exit("result creating", TZDEFAULT);
- }
- tameexit();
- }
-
- /*
- ** Associate sets of rules with zones.
- */
-
- /*
- ** Sort by rule name, and by magnitude of standard time offset for rules of
- ** the same name. The second sort gets standard time entries to the start
- ** of the dsinfo table (and we want a standard time entry at the start of
- ** the table, since the first entry gets used for times not covered by the
- ** rules).
- */
-
- static
- rcomp(cp1, cp2)
- char * cp1;
- char * cp2;
- {
- register struct rule * rp1;
- register struct rule * rp2;
- register long l1, l2;
- register int diff;
-
- rp1 = (struct rule *) cp1;
- rp2 = (struct rule *) cp2;
- if ((diff = strcmp(rp1->r_name, rp2->r_name)) != 0)
- return diff;
- if ((l1 = rp1->r_stdoff) < 0)
- l1 = -l1;
- if ((l2 = rp2->r_stdoff) < 0)
- l2 = -l2;
- if (l1 > l2)
- return 1;
- else if (l1 < l2)
- return -1;
- else return 0;
- }
-
- static
- associate()
- {
- register struct zone * zp;
- register struct rule * rp;
- register int base, out;
- register int i;
-
- if (nrules != 0)
- (void) qsort((char *) rules, nrules, sizeof *rules, rcomp);
- base = 0;
- for (i = 0; i < nzones; ++i) {
- zp = &zones[i];
- zp->z_rules = NULL;
- zp->z_nrules = 0;
- }
- while (base < nrules) {
- rp = &rules[base];
- for (out = base + 1; out < nrules; ++out)
- if (strcmp(rp->r_name, rules[out].r_name) != 0)
- break;
- for (i = 0; i < nzones; ++i) {
- zp = &zones[i];
- if (strcmp(zp->z_rule, rp->r_name) != 0)
- continue;
- zp->z_rules = rp;
- zp->z_nrules = out - base;
- }
- base = out;
- }
- for (i = 0; i < nzones; ++i) {
- zp = &zones[i];
- if (*zp->z_rule != '\0' && zp->z_nrules == 0) {
- filename = zp->z_filename;
- linenum = zp->z_linenum;
- error("unruly zone");
- }
- }
- if (errors)
- wildexit("unruly zone(s)");
- }
-
- static
- error(string)
- char * string;
- {
- (void) fprintf(stderr, "%s: file \"%s\", line %d: wild %s\n",
- progname, filename, linenum, string);
- ++errors;
- }
-
- static
- infile(name)
- char * name;
- {
- register FILE * fp;
- register char ** fields;
- register char * cp;
- register struct lookup * lp;
- register int nfields;
- char buf[BUFSIZ];
-
- if (strcmp(name, "-") == 0) {
- name = "standard input";
- fp = stdin;
- } else if ((fp = fopen(name, "r")) == NULL)
- wild2exit("result opening", name);
- filename = eallocpy(name);
- for (linenum = 1; ; ++linenum) {
- if (fgets(buf, sizeof buf, fp) != buf)
- break;
- cp = strchr(buf, '\n');
- if (cp == NULL) {
- error("long line");
- wildexit("input data");
- }
- *cp = '\0';
- if ((fields = getfields(buf)) == NULL)
- wildrexit("getfields");
- nfields = 0;
- while (fields[nfields] != NULL) {
- if (ciequal(fields[nfields], "-"))
- fields[nfields] = "";
- ++nfields;
- }
- if (nfields > 0) /* non-blank line */
- if ((lp = byword(fields[0], line_codes)) == NULL)
- error("input line of unknown type");
- else switch (lp->l_value) {
- case LC_RULE:
- inrule(fields, nfields);
- break;
- case LC_ZONE:
- inzone(fields, nfields);
- break;
- case LC_LINK:
- inlink(fields, nfields);
- break;
- default: /* "cannot happen" */
- wildrexit("lookup");
- }
- free((char *) fields);
- }
- if (ferror(fp))
- wild2exit("result reading", filename);
- if (fp != stdin && fclose(fp))
- wild2exit("result closing", filename);
- }
-
- /*
- ** Convert a string of one of the forms
- ** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
- ** into a number of seconds.
- ** Call error with errstring and return zero on errors.
- */
-
- static long
- getoff(string, errstring)
- char * string;
- char * errstring;
- {
- long hh, mm, ss, sign;
-
- if (*string == '-') {
- sign = -1;
- ++string;
- } else sign = 1;
- if (sscanf(string, scheck(string, "%ld"), &hh) == 1)
- mm = ss = 0;
- else if (sscanf(string, scheck(string, "%ld:%ld"), &hh, &mm) == 2)
- ss = 0;
- else if (sscanf(string, scheck(string, "%ld:%ld:%ld"),
- &hh, &mm, &ss) != 3) {
- error(errstring);
- return 0;
- }
- if (hh < 0 || hh >= HOURS_PER_DAY ||
- mm < 0 || mm >= MINS_PER_HOUR ||
- ss < 0 || ss >= SECS_PER_MIN) {
- error(errstring);
- return 0;
- }
- return (long) sign * (((hh * MINS_PER_HOUR) + mm) * SECS_PER_MIN + ss);
- }
-
- static
- inrule(fields, nfields)
- char ** fields;
- {
- register struct lookup * lp;
- register char * cp;
- struct rule r;
-
- if (nfields != RULE_FIELDS) {
- error("number of fields on Rule line");
- return;
- }
- r.r_filename = filename;
- r.r_linenum = linenum;
- if ((lp = byword(fields[RF_MONTH], mon_names)) == NULL) {
- error("month name");
- return;
- }
- r.r_month = lp->l_value;
- r.r_todisstd = FALSE;
- cp = fields[RF_TOD];
- if (strlen(cp) > 0) {
- cp += strlen(cp) - 1;
- switch (lowerit(*cp)) {
- case 's':
- r.r_todisstd = TRUE;
- *cp = '\0';
- break;
- case 'w':
- r.r_todisstd = FALSE;
- *cp = '\0';
- break;
- }
- }
- r.r_tod = getoff(fields[RF_TOD], "time of day");
- r.r_stdoff = getoff(fields[RF_STDOFF], "Standard Time offset");
- /*
- ** Year work.
- */
- cp = fields[RF_LOYEAR];
- if (sscanf(cp, scheck(cp, "%ld"), &r.r_loyear) != 1 ||
- r.r_loyear <= 0) {
- error("low year");
- return;
- }
- cp = fields[RF_HIYEAR];
- if (*cp == '\0' || ciequal(cp, "only"))
- r.r_hiyear = r.r_loyear;
- else if (sscanf(cp, scheck(cp, "%ld"), &r.r_hiyear) != 1 ||
- r.r_hiyear <= 0) {
- error("high year");
- return;
- }
- if (r.r_loyear > r.r_hiyear) {
- error("low year (greater than high year)");
- return;
- }
- if (*fields[RF_COMMAND] == '\0')
- r.r_yrtype = NULL;
- else {
- if (r.r_loyear == r.r_hiyear) {
- error("typed single year");
- return;
- }
- r.r_yrtype = eallocpy(fields[RF_COMMAND]);
- }
- /*
- ** Day work.
- ** Accept things such as:
- ** 1
- ** last-Sunday
- ** Sun<=20
- ** Sun>=7
- */
- cp = fields[RF_DAY];
- if ((lp = byword(cp, lasts)) != NULL) {
- r.r_dycode = DC_DOWLEQ;
- r.r_wday = lp->l_value;
- r.r_dayofmonth = mon_lengths[r.r_month];
- if (r.r_month == TM_FEBRUARY)
- ++r.r_dayofmonth;
- } else {
- if ((cp = strchr(fields[RF_DAY], '<')) != 0)
- r.r_dycode = DC_DOWLEQ;
- else if ((cp = strchr(fields[RF_DAY], '>')) != 0)
- r.r_dycode = DC_DOWGEQ;
- else {
- cp = fields[RF_DAY];
- r.r_dycode = DC_DOM;
- }
- if (r.r_dycode != DC_DOM) {
- *cp++ = 0;
- if (*cp++ != '=') {
- error("day of month");
- return;
- }
- if ((lp = byword(fields[RF_DAY], wday_names)) == NULL) {
- error("weekday name");
- return;
- }
- r.r_wday = lp->l_value;
- }
- if (sscanf(cp, scheck(cp, "%ld"), &r.r_dayofmonth) != 1 ||
- r.r_dayofmonth <= 0 ||
- (r.r_dayofmonth > mon_lengths[r.r_month] &&
- r.r_month != TM_FEBRUARY && r.r_dayofmonth != 29)) {
- error("day of month");
- return;
- }
- }
- if (*fields[RF_NAME] == '\0') {
- error("nameless rule");
- return;
- }
- r.r_name = eallocpy(fields[RF_NAME]);
- r.r_abbrvar = eallocpy(fields[RF_ABBRVAR]);
- rules = (struct rule *) erealloc((char *) rules,
- (nrules + 1) * sizeof *rules);
- rules[nrules++] = r;
- }
-
- static
- inzone(fields, nfields)
- char ** fields;
- {
- register char * cp;
- register int i;
- struct zone z;
- char buf[132];
-
- if (nfields != ZONE_FIELDS) {
- error("number of fields on Zone line");
- return;
- }
- z.z_filename = filename;
- z.z_linenum = linenum;
- for (i = 0; i < nzones; ++i)
- if (strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
- (void) sprintf(buf,
- "duplicate zone name %s (file \"%s\", line %d)",
- fields[ZF_NAME],
- zones[i].z_filename,
- zones[i].z_linenum);
- error(buf);
- return;
- }
- z.z_gmtoff = getoff(fields[ZF_GMTOFF], "GMT offset");
- if ((cp = strchr(fields[ZF_FORMAT], '%')) != 0) {
- if (*++cp != 's' || strchr(cp, '%') != 0) {
- error("format");
- return;
- }
- }
- z.z_name = eallocpy(fields[ZF_NAME]);
- z.z_rule = eallocpy(fields[ZF_RULE]);
- z.z_format = eallocpy(fields[ZF_FORMAT]);
- zones = (struct zone *) erealloc((char *) zones,
- (nzones + 1) * sizeof *zones);
- zones[nzones++] = z;
- }
-
- static
- inlink(fields, nfields)
- char ** fields;
- {
- struct link l;
-
- if (nfields != LINK_FIELDS) {
- error("number of fields on Link line");
- return;
- }
- if (*fields[LF_FROM] == '\0') {
- error("blank FROM field on Link line");
- return;
- }
- if (*fields[LF_TO] == '\0') {
- error("blank TO field on Link line");
- return;
- }
- l.l_filename = filename;
- l.l_linenum = linenum;
- l.l_from = eallocpy(fields[LF_FROM]);
- l.l_to = eallocpy(fields[LF_TO]);
- links = (struct link *) erealloc((char *) links,
- (nlinks + 1) * sizeof *links);
- links[nlinks++] = l;
- }
-
- static
- writezone(name)
- char * name;
- {
- register FILE * fp;
- register int i;
- char fullname[BUFSIZ];
-
- if (strlen(directory) + 1 + strlen(name) >= BUFSIZ)
- wild2exit("long directory/file", filename);
- (void) sprintf(fullname, "%s/%s", directory, name);
- if ((fp = fopen(fullname, "w")) == NULL) {
- mkdirs(fullname);
- if ((fp = fopen(fullname, "w")) == NULL)
- wild2exit("result creating", fullname);
- }
- if (fwrite((char *) &h, sizeof h, 1, fp) != 1)
- goto wreck;
- if ((i = h.tzh_timecnt) != 0) {
- if (fwrite((char *) ats, sizeof ats[0], i, fp) != i)
- goto wreck;
- if (fwrite((char *) types, sizeof types[0], i, fp) != i)
- goto wreck;
- }
- if ((i = h.tzh_typecnt) != 0)
- if (fwrite((char *) ttis, sizeof ttis[0], i, fp) != i)
- goto wreck;
- if ((i = h.tzh_charcnt) != 0)
- if (fwrite(chars, sizeof chars[0], i, fp) != i)
- goto wreck;
- if (fclose(fp))
- wild2exit("result closing", fullname);
- return;
- wreck:
- wild2exit("result writing", fullname);
- }
-
- struct temp {
- long t_time;
- struct rule * t_rp;
- };
-
- static struct temp temps[TZ_MAX_TIMES];
- static int ntemps;
-
- static
- tcomp(cp1, cp2)
- char * cp1;
- char * cp2;
- {
- register struct temp * tp1;
- register struct temp * tp2;
- register char * cp;
- register long diff;
-
- tp1 = (struct temp *) cp1;
- tp2 = (struct temp *) cp2;
- if (tp1->t_time > 0 && tp2->t_time <= 0)
- return 1;
- if (tp1->t_time <= 0 && tp2->t_time > 0)
- return -1;
- if ((diff = tp1->t_time - tp2->t_time) > 0)
- return 1;
- else if (diff < 0)
- return -1;
- /*
- ** Oops!
- */
- if (tp1->t_rp->r_type == tp2->t_rp->r_type)
- cp = "duplicate rule?!";
- else cp = "inconsistent rules?!";
- filename = tp1->t_rp->r_filename;
- linenum = tp1->t_rp->r_linenum;
- error(cp);
- filename = tp2->t_rp->r_filename;
- linenum = tp2->t_rp->r_linenum;
- error(cp);
- wildexit(cp);
- /*NOTREACHED*/
- }
-
- static
- addrule(rp, y)
- register struct rule * rp;
- long y;
- {
- if (ntemps >= TZ_MAX_TIMES) {
- error("too many transitions?!");
- wildexit("large number of transitions");
- }
- temps[ntemps].t_time = rpytime(rp, y);
- temps[ntemps].t_rp = rp;
- ++ntemps;
- }
-
- static
- outzone(zp)
- register struct zone * zp;
- {
- register struct rule * rp;
- register int i, j;
- register long y;
- register long gmtoff;
- char buf[BUFSIZ];
-
- h.tzh_timecnt = 0;
- h.tzh_typecnt = 0;
- h.tzh_charcnt = 0;
- if (zp->z_nrules == 0) { /* Piece of cake! */
- h.tzh_timecnt = 0;
- h.tzh_typecnt = 1;
- ttis[0].tt_gmtoff = zp->z_gmtoff;
- ttis[0].tt_isdst = 0;
- ttis[0].tt_abbrind = 0;
- newabbr(zp->z_format);
- writezone(zp->z_name);
- return;
- }
- /*
- ** See what the different local time types are.
- ** Plug the indices into the rules.
- */
- for (i = 0; i < zp->z_nrules; ++i) {
- rp = &zp->z_rules[i];
- (void) sprintf(buf, zp->z_format, rp->r_abbrvar);
- gmtoff = tadd(zp->z_gmtoff, rp->r_stdoff);
- for (j = 0; j < h.tzh_typecnt; ++j) {
- if (gmtoff == ttis[j].tt_gmtoff &&
- strcmp(buf, &chars[ttis[j].tt_abbrind]) == 0)
- break;
- }
- if (j >= h.tzh_typecnt) {
- if (h.tzh_typecnt >= TZ_MAX_TYPES) {
- filename = zp->z_filename;
- linenum = zp->z_linenum;
- error("large number of local time types");
- wildexit("input data");
- }
- ttis[j].tt_gmtoff = gmtoff;
- ttis[j].tt_isdst = rp->r_stdoff != 0;
- ttis[j].tt_abbrind = h.tzh_charcnt;
- newabbr(buf);
- ++h.tzh_typecnt;
- }
- rp->r_type = j;
- }
- /*
- ** Now. . .finally. . .generate some useable data!
- */
- ntemps = 0;
- for (i = 0; i < zp->z_nrules; ++i) {
- rp = &zp->z_rules[i];
- filename = rp->r_filename;
- linenum = rp->r_linenum;
- if (rp->r_yrtype != NULL && *rp->r_yrtype != '\0')
- hard(rp);
- else for (y = rp->r_loyear; y <= rp->r_hiyear; ++y)
- addrule(rp, y);
- }
- h.tzh_timecnt = ntemps;
- (void) qsort((char *) temps, ntemps, sizeof *temps, tcomp);
- for (i = 0; i < ntemps; ++i) {
- rp = temps[i].t_rp;
- filename = rp->r_filename;
- linenum = rp->r_linenum;
- types[i] = rp->r_type;
- ats[i] = tadd(temps[i].t_time, -zp->z_gmtoff);
- if (!rp->r_todisstd) {
- /*
- ** Credit to munnari!kre for pointing out the need for
- ** the following. (This can still mess up on the
- ** earliest rule; who's got the solution? It can also
- ** mess up if a time switch results in a day switch;
- ** this is left as an exercise for the reader.)
- */
- if (i == 0) {
- /*
- ** Kludge--not guaranteed to work.
- */
- if (ntemps > 1)
- ats[0] = tadd(ats[0],
- -temps[1].t_rp->r_stdoff);
- } else ats[i] = tadd(ats[i],
- -temps[i - 1].t_rp->r_stdoff);
- }
- }
- writezone(zp->z_name);
- return;
- }
-
- static
- hard(rp)
- register struct rule * rp;
- {
- register FILE * fp;
- register int n;
- long y;
- char buf[BUFSIZ];
- char command[BUFSIZ];
-
- (void) sprintf(command, "years %ld %ld %s",
- rp->r_loyear, rp->r_hiyear, rp->r_yrtype);
- if ((fp = popen(command, "r")) == NULL)
- wild2exit("result opening pipe to", command);
- for (n = 0; fgets(buf, sizeof buf, fp) == buf; ++n) {
- if (strchr(buf, '\n') == 0)
- wildrexit(command);
- *strchr(buf, '\n') = '\0';
- if (sscanf(buf, scheck(buf, "%ld"), &y) != 1)
- wildrexit(command);
- if (y < rp->r_loyear || y > rp->r_hiyear)
- wildrexit(command);
- addrule(rp, y);
- }
- if (ferror(fp))
- wild2exit("result reading from", command);
- if (pclose(fp))
- wild2exit("result closing pipe to", command);
- if (n == 0) {
- error("no year in range matches type");
- wildexit("input data");
- }
- }
-
- static
- lowerit(a)
- {
- return (isascii(a) && isupper(a)) ? tolower(a) : a;
- }
-
- static
- ciequal(ap, bp) /* case-insensitive equality */
- register char * ap;
- register char * bp;
- {
- while (lowerit(*ap) == lowerit(*bp++))
- if (*ap++ == '\0')
- return TRUE;
- return FALSE;
- }
-
- static
- isabbr(abbr, word)
- register char * abbr;
- register char * word;
- {
- if (lowerit(*abbr) != lowerit(*word))
- return FALSE;
- ++word;
- while (*++abbr != '\0')
- do if (*word == '\0')
- return FALSE;
- while (lowerit(*word++) != lowerit(*abbr));
- return TRUE;
- }
-
- static struct lookup *
- byword(word, table)
- register char * word;
- register struct lookup * table;
- {
- register struct lookup * foundlp;
- register struct lookup * lp;
-
- if (word == NULL || table == NULL)
- return NULL;
- foundlp = NULL;
- for (lp = table; lp->l_word != NULL; ++lp)
- if (ciequal(word, lp->l_word)) /* "exact" match */
- return lp;
- else if (!isabbr(word, lp->l_word))
- continue;
- else if (foundlp == NULL)
- foundlp = lp;
- else return NULL; /* two inexact matches */
- return foundlp;
- }
-
- static char **
- getfields(cp)
- register char * cp;
- {
- register char * dp;
- register char ** array;
- register int nsubs;
-
- if (cp == NULL)
- return NULL;
- array = (char **) emalloc((strlen(cp) + 1) * sizeof *array);
- nsubs = 0;
- for ( ; ; ) {
- while (isascii(*cp) && isspace(*cp))
- ++cp;
- if (*cp == '\0' || *cp == '#')
- break;
- array[nsubs++] = dp = cp;
- do {
- if ((*dp = *cp++) != '"')
- ++dp;
- else while ((*dp = *cp++) != '"')
- if (*dp != '\0')
- ++dp;
- else error("Odd number of quotation marks");
- } while (*cp != '\0' && *cp != '#' &&
- (!isascii(*cp) || !isspace(*cp)));
- if (isascii(*cp) && isspace(*cp))
- ++cp;
- *dp++ = '\0';
- }
- array[nsubs] = NULL;
- return array;
- }
-
- static long
- tadd(t1, t2)
- long t1;
- long t2;
- {
- register long t;
-
- t = t1 + t2;
- if (t1 > 0 && t2 > 0 && t <= 0 || t1 < 0 && t2 < 0 && t >= 0) {
- error("time overflow");
- wildexit("time overflow");
- }
- return t;
- }
-
- static
- isleap(y)
- long y;
- {
- return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
- }
-
- static long
- rpytime(rp, wantedy)
- register struct rule * rp;
- register long wantedy;
- {
- register long i, y, wday, t, m;
- register long dayoff; /* with a nod to Margaret O. */
-
- dayoff = 0;
- m = TM_JANUARY;
- y = EPOCH_YEAR;
- while (wantedy != y) {
- if (wantedy > y) {
- i = DAYS_PER_YEAR;
- if (isleap(y))
- ++i;
- ++y;
- } else {
- --y;
- i = -DAYS_PER_YEAR;
- if (isleap(y))
- --i;
- }
- dayoff = tadd(dayoff, i);
- }
- while (m != rp->r_month) {
- i = mon_lengths[m];
- if (m == TM_FEBRUARY && isleap(y))
- ++i;
- dayoff = tadd(dayoff, i);
- ++m;
- }
- i = rp->r_dayofmonth;
- if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
- if (rp->r_dycode == DC_DOWLEQ)
- --i;
- else {
- error("use of 2/29 in non leap-year");
- for ( ; ; )
- wildexit("data");
- }
- }
- --i;
- dayoff = tadd(dayoff, i);
- if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
- wday = EPOCH_WDAY;
- /*
- ** Don't trust mod of negative numbers.
- */
- if (dayoff >= 0)
- wday = (wday + dayoff) % 7;
- else {
- wday -= ((-dayoff) % 7);
- if (wday < 0)
- wday += 7;
- }
- while (wday != rp->r_wday) {
- if (rp->r_dycode == DC_DOWGEQ)
- i = 1;
- else i = -1;
- dayoff = tadd(dayoff, i);
- wday = (wday + i + 7) % 7;
- }
- }
- t = dayoff * SECS_PER_DAY;
- /*
- ** Cheap overflow check.
- */
- if (t / SECS_PER_DAY != dayoff)
- error("time overflow");
- return tadd(t, rp->r_tod);
- }
-
- static
- newabbr(string)
- char * string;
- {
- register int i;
-
- i = strlen(string);
- if (h.tzh_charcnt + i >= TZ_MAX_CHARS)
- error("long time zone abbreviations");
- (void) strcpy(&chars[h.tzh_charcnt], string);
- h.tzh_charcnt += i + 1;
- }
-
- static
- mkdirs(name)
- char * name;
- {
- register char * cp;
-
- if ((cp = name) == NULL || *cp == '\0')
- return;
- while ((cp = strchr(cp + 1, '/')) != 0) {
- *cp = '\0';
- (void) mkdir(name);
- *cp = '/';
- }
- }
- SHAR_EOF
- if test 24558 -ne "`wc -c < 'tzcomp.c'`"
- then
- echo shar: error transmitting "'tzcomp.c'" '(should have been 24558 characters)'
- fi
- fi
- echo shar: extracting "'scheck.c'" '(1141 characters)'
- if test -f 'scheck.c'
- then
- echo shar: will not over-write existing file "'scheck.c'"
- else
- cat << \SHAR_EOF > 'scheck.c'
- #
-
- /*LINTLIBRARY*/
-
- #include "stdio.h"
-
- #ifdef OBJECTID
- static char sccsid[] = "@(#)scheck.c 7.9";
- #endif
-
- #include "ctype.h"
-
- #ifndef alloc_t
- #define alloc_t unsigned
- #endif
-
- #ifndef MAL
- #define MAL NULL
- #endif
-
- extern char * malloc();
-
- char *
- scheck(string, format)
- char * string;
- char * format;
- {
- register char * fbuf;
- register char * fp;
- register char * tp;
- register int c;
- register char * result;
- char dummy;
-
- result = "";
- if (string == NULL || format == NULL)
- return result;
- fbuf = malloc((alloc_t) (2 * strlen(format) + 4));
- if (fbuf == MAL)
- return result;
- fp = format;
- tp = fbuf;
- while ((*tp++ = c = *fp++) != '\0') {
- if (c != '%')
- continue;
- if (*fp == '%') {
- *tp++ = *fp++;
- continue;
- }
- *tp++ = '*';
- if (*fp == '*')
- ++fp;
- while (isascii(*fp) && isdigit(*fp))
- *tp++ = *fp++;
- if (*fp == 'l' || *fp == 'h')
- *tp++ = *fp++;
- else if (*fp == '[')
- do *tp++ = *fp++;
- while (*fp != '\0' && *fp != ']');
- if ((*tp++ = *fp++) == '\0')
- break;
- }
- *(tp - 1) = '%';
- *tp++ = 'c';
- *tp++ = '\0';
- if (sscanf(string, fbuf, &dummy) != 1)
- result = format;
- free(fbuf);
- return result;
- }
- SHAR_EOF
- if test 1141 -ne "`wc -c < 'scheck.c'`"
- then
- echo shar: error transmitting "'scheck.c'" '(should have been 1141 characters)'
- fi
- fi
- echo shar: extracting "'strchr.c'" '(419 characters)'
- if test -f 'strchr.c'
- then
- echo shar: will not over-write existing file "'strchr.c'"
- else
- cat << \SHAR_EOF > 'strchr.c'
- #
-
- /*LINTLIBRARY*/
-
- #include "stdio.h"
-
- #ifdef OBJECTID
- static char sccsid[] = "@(#)strchr.c 7.3";
- #endif
-
- /*
- ** For the benefit of BSD folks.
- ** This is written from the manual description,
- ** so there's no guarantee that it works the same as the "real thing."
- */
-
- char *
- strchr(string, c)
- register char * string;
- register int c;
- {
- do if (*string == c)
- return string;
- while (*string++ != '\0');
- return NULL;
- }
- SHAR_EOF
- if test 419 -ne "`wc -c < 'strchr.c'`"
- then
- echo shar: error transmitting "'strchr.c'" '(should have been 419 characters)'
- fi
- fi
- echo shar: extracting "'mkdir.c'" '(524 characters)'
- if test -f 'mkdir.c'
- then
- echo shar: will not over-write existing file "'mkdir.c'"
- else
- cat << \SHAR_EOF > 'mkdir.c'
- #
-
- /*LINTLIBRARY*/
-
- #include "stdio.h"
-
- #ifdef OJBECTID
- static char sccsid[] = "@(#)mkdir.c 7.2";
- #endif
-
- extern FILE * popen();
-
- mkdir(name)
- char * name;
- {
- register FILE * fp;
- register int c;
- register int oops;
-
- if ((fp = popen("sh", "w")) == NULL)
- return -1;
- (void) fputs("mkdir 2>&- '", fp);
- if (name != NULL)
- while ((c = *name++) != '\0')
- if (c == '\'')
- (void) fputs("'\\''", fp);
- else (void) fputc(c, fp);
- (void) fputs("'\n", fp);
- oops = ferror(fp);
- return (pclose(fp) == 0 && !oops) ? 0 : -1;
- }
- SHAR_EOF
- if test 524 -ne "`wc -c < 'mkdir.c'`"
- then
- echo shar: error transmitting "'mkdir.c'" '(should have been 524 characters)'
- fi
- fi
- echo shar: extracting "'tzdump.c'" '(2783 characters)'
- if test -f 'tzdump.c'
- then
- echo shar: will not over-write existing file "'tzdump.c'"
- else
- cat << \SHAR_EOF > 'tzdump.c'
- #
-
- #include "stdio.h"
-
- #ifdef OBJECTID
- static char sccsid[] = "@(#)tzdump.c 2.1";
- #endif
-
- #include "time.h"
- #include "tzfile.h"
-
- #ifndef alloc_t
- #define alloc_t unsigned
- #endif
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
-
- extern char * asctime();
- extern char * calloc();
- extern struct tm * gmtime();
- extern char * newctime();
- extern int optind;
- extern char * sprintf();
- extern long time();
- extern char * tz_abbr;
-
- static int longest;
-
- main(argc, argv)
- int argc;
- char * argv[];
- {
- register FILE * fp;
- register long * tp;
- register int i, j, c;
- register int vflag;
- long now;
- struct tzhead h;
- char buf[BUFSIZ];
-
- vflag = 0;
- while ((c = getopt(argc, argv, "v")) == 'v')
- vflag = 1;
- if (c != EOF || optind == argc - 1 && strcmp(argv[optind], "=") == 0) {
- (void) fprintf(stderr, "%s: usage is %s [ -v ] zonename ...\n",
- argv[0], argv[0]);
- exit(1);
- }
- (void) time(&now);
- longest = 0;
- for (i = optind; i < argc; ++i)
- if (strlen(argv[i]) > longest)
- longest = strlen(argv[i]);
- for (i = optind; i < argc; ++i) {
- if (settz(argv[i]) != 0) {
- (void) fprintf(stderr,
- "%s: wild result from settz(\"%s\")\n",
- argv[0], argv[i]);
- exit(1);
- }
- show(argv[i], now, FALSE);
- if (!vflag)
- continue;
- if (argv[i][0] == '/')
- fp = fopen(argv[i], "r");
- else {
- j = strlen(TZDIR) + 1 + strlen(argv[i]) + 1;
- if (j > sizeof buf) {
- (void) fprintf(stderr,
- "%s: wild long timezone name %s\n",
- argv[0], argv[i]);
- exit(1);
- }
- (void) sprintf(buf, "%s/%s", TZDIR, argv[i]);
- fp = fopen(buf, "r");
- }
- if (fp == NULL) {
- (void) fprintf(stderr,
- "%s: wild result opening %s file\n",
- argv[0], argv[i]);
- exit(1);
- }
- if (fread((char *) &h, sizeof h, 1, fp) != 1) {
- (void) fprintf(stderr,
- "%s: wild result reading %s file\n",
- argv[0], argv[i]);
- exit(1);
- }
- tp = (long *) calloc((alloc_t) h.tzh_timecnt, sizeof *tp);
- if (tp == NULL) {
- (void) fprintf(stderr,
- "%s: wild result from calloc\n", argv[0]);
- exit(1);
- }
- if (h.tzh_timecnt != 0)
- if (fread((char *) tp, sizeof *tp, (int) h.tzh_timecnt,
- fp) != h.tzh_timecnt) {
- (void) fprintf(stderr,
- "%s: wild result reading %s file\n",
- argv[0], argv[i]);
- exit(1);
- }
- if (fclose(fp)) {
- (void) fprintf(stderr,
- "%s: wild result closing %s file\n",
- argv[0], argv[i]);
- exit(1);
- }
- for (j = 0; j < h.tzh_timecnt; ++j) {
- show(argv[i], tp[j] - 1, TRUE);
- show(argv[i], tp[j], TRUE);
- }
- free((char *) tp);
- }
- return 0;
- }
-
- static
- show(zone, t, v)
- char * zone;
- long t;
- {
- (void) printf("%-*s ", longest, zone);
- if (v)
- (void) printf("%.24s GMT = ", asctime(gmtime(&t)));
- (void) printf("%.24s", newctime(&t));
- if (*tz_abbr != '\0')
- (void) printf(" %s", tz_abbr);
- (void) printf("\n");
- }
- SHAR_EOF
- if test 2783 -ne "`wc -c < 'tzdump.c'`"
- then
- echo shar: error transmitting "'tzdump.c'" '(should have been 2783 characters)'
- fi
- fi
- echo shar: extracting "'settz.c'" '(4052 characters)'
- if test -f 'settz.c'
- then
- echo shar: will not over-write existing file "'settz.c'"
- else
- cat << \SHAR_EOF > 'settz.c'
- #
-
- /*LINTLIBRARY*/
-
- /*
- ** Should there be any built-in rules other than GMT?
- ** In particular, should zones such as "EST5" (abbreviation is always "EST",
- ** GMT offset is always 5 hours) be built in?
- */
-
- #include "tzfile.h"
- #include "time.h"
-
- #ifdef OBJECTID
- static char sccsid[] = "@(#)settz.c 2.1";
- #endif
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
-
- #ifndef MAXPATHLEN
- #define MAXPATHLEN 1024
- #endif
-
- extern char * asctime();
- extern struct tm * gmtime();
- extern char * strcpy();
- extern char * strcat();
- extern char * getenv();
-
- static struct tzhead h;
- static long ats[TZ_MAX_TIMES];
- static unsigned char types[TZ_MAX_TIMES];
- static struct ttinfo ttis[TZ_MAX_TYPES];
- static char chars[TZ_MAX_CHARS + 1];
-
- #define TZ_MAX_TOTAL (sizeof h + sizeof ats + sizeof types + \
- sizeof ttis + sizeof chars)
-
- static char isset;
-
- char * tz_abbr; /* set by localtime; available to all */
-
- /*
- ** Not available west of the Rockies. . .
- */
-
- static char *
- memcpy(to, from, n)
- char * to;
- char * from;
- {
- register int i;
-
- for (i = 0; i < n; ++i)
- to[i] = from[i];
- return to;
- }
-
- static
- tzload(tzname)
- register char * tzname;
- {
- register char * p;
- register int fid;
- register int i;
- register int doaccess;
- char buf[(TZ_MAX_TOTAL>MAXPATHLEN)?TZ_MAX_TOTAL:MAXPATHLEN];
-
- if (tzname == 0 && (tzname = TZDEFAULT) == 0)
- return -1;
- doaccess = tzname[0] == '/';
- if (!doaccess) {
- if ((p = TZDIR) == 0)
- return -1;
- if ((strlen(p) + strlen(tzname) + 1) >= sizeof buf)
- return -1;
- (void) strcpy(buf, p);
- (void) strcat(buf, "/");
- (void) strcat(buf, tzname);
- /*
- ** Set doaccess if '.' (as in "../") shows up in name.
- */
- while (*tzname != '\0')
- if (*tzname++ == '.')
- doaccess = TRUE;
- tzname = buf;
- }
- if (doaccess && access(tzname, 4) != 0)
- return -1;
- if ((fid = open(tzname, 0)) == -1)
- return -1;
- p = buf;
- i = read(fid, p, sizeof buf);
- if (close(fid) != 0 || i < sizeof h)
- return -1;
- (void) memcpy((char *) &h, p, sizeof h);
- if (h.tzh_timecnt > TZ_MAX_TIMES ||
- h.tzh_typecnt == 0 || h.tzh_typecnt > TZ_MAX_TYPES ||
- h.tzh_charcnt > TZ_MAX_CHARS)
- return -1;
- if (i < sizeof h +
- h.tzh_timecnt * (sizeof ats[0] + sizeof types[0]) +
- h.tzh_typecnt * sizeof ttis[0] +
- h.tzh_charcnt * sizeof chars[0])
- return -1;
- p += sizeof h;
- if ((i = h.tzh_timecnt) > 0) {
- (void) memcpy((char *) ats, p, i * sizeof ats[0]);
- p += i * sizeof ats[0];
- (void) memcpy((char *) types, p, i * sizeof types[0]);
- p += i * sizeof types[0];
- }
- if ((i = h.tzh_typecnt) > 0) {
- (void) memcpy((char *) ttis, p, i * sizeof ttis[0]);
- p += i * sizeof ttis[0];
- }
- if ((i = h.tzh_charcnt) > 0)
- (void) memcpy((char *) chars, p, i * sizeof chars[0]);
- chars[h.tzh_charcnt] = '\0'; /* ensure '\0'-termination */
- for (i = 0; i < h.tzh_timecnt; ++i)
- if (types[i] >= h.tzh_typecnt)
- return -1;
- for (i = 0; i < h.tzh_typecnt; ++i)
- if (ttis[i].tt_abbrind >= h.tzh_charcnt)
- return -1;
- return 0;
- }
-
- /*
- ** settz("") Use built-in GMT.
- ** settz((char *) 0) Use TZDEFAULT.
- ** settz(otherwise) Use otherwise.
- */
-
- settz(tzname)
- char * tzname;
- {
- register int answer;
-
- isset = TRUE;
- if (tzname != 0 && *tzname == '\0')
- answer = 0; /* Use built-in GMT */
- else {
- if (tzload(tzname) == 0)
- return 0;
- /*
- ** If we want to try for local time on errors. . .
- if (tzload((char *) 0) == 0)
- return -1;
- */
- answer = -1;
- }
- h.tzh_timecnt = 0;
- ttis[0].tt_gmtoff = 0;
- ttis[0].tt_abbrind = 0;
- (void) strcpy(chars, "GMT");
- return answer;
- }
-
- struct tm *
- newlocaltime(timep)
- long * timep;
- {
- register struct ttinfo * ttip;
- register struct tm * tmp;
- register int i;
- long t;
-
- t = *timep;
- if (!isset)
- (void) settz(getenv("TZ"));
- if (h.tzh_timecnt == 0 || t < ats[0])
- i = 0;
- else {
- for (i = 1; i < h.tzh_timecnt; ++i)
- if (t < ats[i])
- break;
- i = types[i - 1];
- }
- ttip = &ttis[i];
- t += ttip->tt_gmtoff;
- tmp = gmtime(&t);
- tmp->tm_isdst = ttip->tt_isdst;
- tz_abbr = &chars[ttip->tt_abbrind];
- return tmp;
- }
-
- char *
- newctime(timep)
- long * timep;
- {
- return asctime(newlocaltime(timep));
- }
- SHAR_EOF
- if test 4052 -ne "`wc -c < 'settz.c'`"
- then
- echo shar: error transmitting "'settz.c'" '(should have been 4052 characters)'
- fi
- fi
- echo shar: extracting "'years.sh'" '(382 characters)'
- if test -f 'years.sh'
- then
- echo shar: will not over-write existing file "'years.sh'"
- else
- cat << \SHAR_EOF > 'years.sh'
- : '@(#)years.sh 2.1'
-
- : years lo hi type
-
- case $# in
- 3) ;;
- *) echo "$0: usage is $0 lo hi type" 1>&2
- exit 1 ;;
- esac
-
- lo="$1"
- hi="$2"
- type="$3"
-
- case $type in
- uspres) check='(y % 4) == 0' ;;
- nonpres) check='(y % 4) != 0' ;;
- *) echo "$0: wild year type ($type)" 1>&2
- exit 1 ;;
- esac
-
- exec awk "
- BEGIN {
- for (y = $lo; y <= $hi; ++y)
- if ($check)
- print y;
- exit
- }
- "
- SHAR_EOF
- if test 382 -ne "`wc -c < 'years.sh'`"
- then
- echo shar: error transmitting "'years.sh'" '(should have been 382 characters)'
- fi
- fi
- echo shar: extracting "'asia'" '(71 characters)'
- if test -f 'asia'
- then
- echo shar: will not over-write existing file "'asia'"
- else
- cat << \SHAR_EOF > 'asia'
- # @(#)asia 2.1
- # Zone NAME GMTOFF RULES FORMAT
- Zone Japan 9:00 - JST
- SHAR_EOF
- if test 71 -ne "`wc -c < 'asia'`"
- then
- echo shar: error transmitting "'asia'" '(should have been 71 characters)'
- fi
- fi
- echo shar: extracting "'australasia'" '(942 characters)'
- if test -f 'australasia'
- then
- echo shar: will not over-write existing file "'australasia'"
- else
- cat << \SHAR_EOF > 'australasia'
- # @(#)australasia 2.1
-
- # Australian Data (for states with DST), standard rules
-
- # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
- Rule Aus 1971 2037 - Oct lastSun 2:00 1:00 -
- Rule Aus 1972 only - Feb 27 3:00 0 -
- Rule Aus 1973 2037 - Mar Sun>=1 3:00 0 -
-
- #Australian Data, Vic (and NSW except for a variation in 83? that I[kre] forget)
-
- Rule Aus-Vic 1971 2037 - Oct lastSun 2:00 1:00 -
- Rule Aus-Vic 1972 only - Feb 27 3:00 0 -
- Rule Aus-Vic 1973 1985 - Mar Sun>=1 3:00 0 -
- # is this really forever, or just 86??
- Rule Aus-Vic 1986 2037 - Mar Sun<=21 3:00 0 -
-
- # Australia - something of a turmoil here
- # Zone NAME GMTOFF RULES FORMAT
- Zone EST 10:00 Aus-Vic EST # rule change, 1986
- Zone Tasmania 10:00 Aus EST # still the standard rules?
- Zone Queensland 10:00 - EST # Queensland - no DST
- Zone CST 9:30 Aus CST # still the standard rules?
- Zone North 9:30 - CST # Northern Territory - no DST
- Zone WST 8:00 - WST # No DST ever, this is simple...
- SHAR_EOF
- if test 942 -ne "`wc -c < 'australasia'`"
- then
- echo shar: error transmitting "'australasia'" '(should have been 942 characters)'
- fi
- fi
- echo shar: extracting "'europe'" '(930 characters)'
- if test -f 'europe'
- then
- echo shar: will not over-write existing file "'europe'"
- else
- cat << \SHAR_EOF > 'europe'
- # @(#)europe 2.1
-
- # European data is hearsay...
-
- # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
- Rule W-Eur 1969 2037 - Mar lastSun 2:00 1:00 " DST"
- Rule W-Eur 1969 1982 - Oct lastSun 2:00 0 -
- Rule W-Eur 1983 only - Oct 23 2:00 0 -
- Rule W-Eur 1984 2037 - Oct lastSun 2:00 0 -
-
- Rule M-Eur 1969 2037 - Mar lastSun 2:00 1:00 " DST"
- Rule M-Eur 1969 1982 - Sep lastSun 2:00 0 -
- Rule M-Eur 1983 only - Oct 23 2:00 0 -
- Rule M-Eur 1984 2037 - Sep lastSun 2:00 0 -
-
- # Zone NAME GMTOFF RULES FORMAT
- Zone WET 0 W-Eur WET%s
- Zone MET 1 M-Eur MET%s
-
- # One source shows that Bulgaria, Cyprus, Finland, and Greece observe DST from
- # the last Sunday in March to the last Sunday in September in 1986.
- # Did any/all of them have Middle Europe's 1983 wobble?
- #
- # The source shows Romania changing a day later than everybody else;
- # since I don't think they're allowed to have UNIX(tm) systems, we'll skip
- # them for now.
-
- Zone EET 2 M-Eur EET%s
- SHAR_EOF
- if test 930 -ne "`wc -c < 'europe'`"
- then
- echo shar: error transmitting "'europe'" '(should have been 930 characters)'
- fi
- fi
- echo shar: extracting "'etcetera'" '(1208 characters)'
- if test -f 'etcetera'
- then
- echo shar: will not over-write existing file "'etcetera'"
- else
- cat << \SHAR_EOF > 'etcetera'
- # @(#)etcetera 2.1
-
- #
- # A settz("") uses the code's built-in GMT without going to disk to get
- # the information. Still, we want things to work if somebody does a
- # settz("GMT"), so. . .
- #
-
- Zone GMT 0 - GMT
-
- #
- # Names for zones that might exist, just so people can set a timezone
- # that's right for their area, even if it doesn't have a name or dst rules
- # (half hour zones are too much to bother with -- when someone asks!)
- #
-
- Zone GMT-12 -12 - GMT-1200
- Zone GMT-11 -11 - GMT-1100
- Zone GMT-10 -10 - GMT-1000
- Zone GMT-9 -9 - GMT-0900
- Zone GMT-8 -8 - GMT-0800
- Zone GMT-7 -7 - GMT-0700
- Zone GMT-6 -6 - GMT-0600
- Zone GMT-5 -5 - GMT-0500
- Zone GMT-4 -4 - GMT-0400
- Zone GMT-3 -3 - GMT-0300
- Zone GMT-2 -2 - GMT-0200
- Zone GMT-1 -1 - GMT-0100
- Zone GMT+1 1 - GMT+0100
- Zone GMT+2 2 - GMT+0200
- Zone GMT+3 3 - GMT+0300
- Zone GMT+4 4 - GMT+0400
- Zone GMT+5 5 - GMT+0500
- Zone GMT+6 6 - GMT+0600
- Zone GMT+7 7 - GMT+0700
- Zone GMT+8 8 - GMT+0800
- Zone GMT+9 9 - GMT+0900
- Zone GMT+10 10 - GMT+1000
- Zone GMT+11 11 - GMT+1100
- Zone GMT+12 12 - GMT+1200
- Zone GMT+13 13 - GMT+1300 # GMT+12 with DST
-
- Link GMT UTC # one of these two is right, but which?
- Link GMT UCT
- Link GMT Universal
- Link GMT Greenwich
- SHAR_EOF
- if test 1208 -ne "`wc -c < 'etcetera'`"
- then
- echo shar: error transmitting "'etcetera'" '(should have been 1208 characters)'
- fi
- fi
- echo shar: extracting "'northamerica'" '(3139 characters)'
- if test -f 'northamerica'
- then
- echo shar: will not over-write existing file "'northamerica'"
- else
- cat << \SHAR_EOF > 'northamerica'
- # @(#)northamerica 2.1
-
- # Bob Devine has written that ". . .your table is wrong for MostNA in 1974.
- # The correct ending date is 10/27 not 11/24." Yet on a 4.1bsd VAX/11-750
- # system, compiling and executing the program
- #
- # #include "time.h"
- #
- # long l = 152592000;
- #
- # main() {
- # struct tm * tmp;
- #
- # tmp = localtime(&l);
- # printf("%s", asctime(tmp));
- # printf("isdst: %d\n", tmp->tm_isdst);
- # }
- #
- # results in the output
- #
- # Fri Nov 1 22:40:00 1974
- # isdst: 1
- #
- # For now we'll stay with 4.1bsd's version.
- #
- # Note also this from munnari!kre:
- # "I recall also being told by someone once that Canada didn't have
- # the DST variations in 74/75 that the US did, but I am not nearly
- # sure enough of this to add anything."
-
- # Before the Uniform Time Act of 1966 took effect in 1967, observance of
- # Daylight Saving Time in the US was by local option, except during wartime.
-
- # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
- Rule MostNA 1918 1919 - Mar lastSun 2:00 1:00 D
- Rule MostNA 1918 1919 - Oct lastSun 2:00 0 S
- Rule MostNA 1942 only - Feb 9 2:00 1:00 W # War
- Rule MostNA 1945 only - Sep 30 2:00 0 S
- Rule MostNA 1967 1973 - Apr lastSun 2:00 1:00 D
- Rule MostNA 1967 1973 - Oct lastSun 2:00 0 S
- Rule MostNA 1974 only - Jan 6 2:00 1:00 D
- Rule MostNA 1974 only - Nov 24 2:00 0 S
- Rule MostNA 1975 only - Feb 23 2:00 1:00 D
- Rule MostNA 1975 only - Oct 26 2:00 0 S
- Rule MostNA 1976 2037 - Apr lastSun 2:00 1:00 D
- Rule MostNA 1976 2037 - Oct lastSun 2:00 0 S
-
- ###############################################################################
-
- # New names
-
- # Zone NAME GMTOFF RULES FORMAT
- Zone Atlantic -4:00 MostNA A%sT
- Zone Eastern -5:00 MostNA E%sT
- Zone Central -6:00 MostNA C%sT
- Zone Mountain -7:00 MostNA M%sT
- Zone Pacific -8:00 MostNA P%sT
- Zone Yukon -9:00 MostNA Y%sT
- Zone Aleutian -10:00 MostNA A%sT
- Zone Newfoundland -3:30 - NST # Is DST now observed here?
- # If so, when did it start?
-
- # Old names
-
- # Link LINK-FROM LINK-TO
- Link Eastern EST5EDT
- Link Central CST6CDT
- Link Mountain MST7MDT
- Link Pacific PST8PDT
-
- # Nonstandard mainland areas:
-
- Rule SomeUS 1918 1919 - Mar lastSun 2:00 1:00 D
- Rule SomeUS 1918 1919 - Oct lastSun 2:00 0 S
- Rule SomeUS 1942 only - Feb 9 2:00 1:00 W # War
- Rule SomeUS 1945 only - Sep 30 2:00 0 S
-
- Zone East-Indiana -5:00 SomeUS E%sT # Usually standard near South Bend
- Zone Arizona -7:00 SomeUS M%sT # Usually standard in Arizona
-
- # And then there's Hawaii.
- # DST was observed for one day in 1933.
- # Standard time was change by half an hour in 1947; this accounts for
- # the half-hour offsets before then, and the peculiar first rule.
- # (An alternative is to have "Zone Hawaiian -10:30..." with a
- # current standard offset of 0:30; this seems a bit more obscure.)
- #
- # Things have been calm since 1947.
-
- Rule Hawaii 1901 only - Dec 14 0:00 -0:30 S
- Rule Hawaii 1918 1919 - Mar lastSun 2:00 0:30 D
- Rule Hawaii 1918 1919 - Oct lastSun 2:00 -0:30 S
- Rule Hawaii 1933 only - Apr 30 2:00 0:30 D
- Rule Hawaii 1933 only - May 1 2:00 -0:30 S
- Rule Hawaii 1942 only - Feb 9 2:00 0:30 W # War
- Rule Hawaii 1945 only - Sep 30 2:00 -0:30 S
- Rule Hawaii 1947 only - Jun 8 2:00 0 S
-
- Zone Hawaiian -10:00 Hawaii H%sT
- SHAR_EOF
- if test 3139 -ne "`wc -c < 'northamerica'`"
- then
- echo shar: error transmitting "'northamerica'" '(should have been 3139 characters)'
- fi
- fi
- echo shar: extracting "'pacificnew'" '(922 characters)'
- if test -f 'pacificnew'
- then
- echo shar: will not over-write existing file "'pacificnew'"
- else
- cat << \SHAR_EOF > 'pacificnew'
- # @(#)pacificnew 2.1
-
- # "Pacific Presidential Election Time" is being contemplated by the US Congress
-
- # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
- Rule Twilite 1918 1919 - Mar lastSun 2:00 1:00 D
- Rule Twilite 1918 1919 - Oct lastSun 2:00 0 S
- Rule Twilite 1942 only - Feb 9 2:00 1:00 W # War
- Rule Twilite 1945 only - Sep 30 2:00 0 S
- Rule Twilite 1967 1973 - Apr lastSun 2:00 1:00 D
- Rule Twilite 1967 1973 - Oct lastSun 2:00 0 S
- Rule Twilite 1974 only - Jan 6 2:00 1:00 D
- Rule Twilite 1974 only - Nov 24 2:00 0 S
- Rule Twilite 1975 only - Feb 23 2:00 1:00 D
- Rule Twilite 1975 only - Oct 26 2:00 0 S
- Rule Twilite 1976 2037 - Apr lastSun 2:00 1:00 D
- Rule Twilite 1976 1987 - Oct lastSun 2:00 0 S
- Rule Twilite 1988 2037 uspres Oct lastSun 2:00 1:00 PE
- Rule Twilite 1988 2037 uspres Nov Sun>=7 2:00 0 S
- Rule Twilite 1988 2037 nonpres Oct lastSun 2:00 0 S
-
- # Zone NAME GMTOFF RULES FORMAT
- Zone Pacific-New -8:00 Twilite P%sT
- SHAR_EOF
- if test 922 -ne "`wc -c < 'pacificnew'`"
- then
- echo shar: error transmitting "'pacificnew'" '(should have been 922 characters)'
- fi
- fi
- exit 0
- # End of shell archive
-